package com.gitee.hermer.engine.jars.core.context.impl;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.stereotype.Component;

import com.gitee.hermer.boot.jee.commons.collection.StringCache;
import com.gitee.hermer.boot.jee.commons.exception.ErrorCode;
import com.gitee.hermer.boot.jee.commons.log.UtilsContext;
import com.gitee.hermer.boot.jee.commons.verify.Assert;
import com.gitee.hermer.engine.jars.core.context.IEngineAppContext;
import com.gitee.hermer.engine.jars.core.context.domain.EngineAppContext;
import com.gitee.hermer.engine.jars.core.domain.EngineConstant;

@Component
public class EngineAppContextImpl extends UtilsContext implements IEngineAppContext{

	public EngineAppContextImpl(){
	}

	private static Map<String, EngineAppLoaderState> cacheAppLoaderState = null;

	private static Map<String, EngineAppContext> appsContext = null;


	public enum EngineAppLoaderState{
		UPDATE, // 文件更新
		BEGIN_INIT,// 初始化之前
		INIT_ING, //初始化中
		END_INIT, // 初始化完毕
		RUN_ING, //运行中
		BEGIN_DESTROY, // 销毁前
		END_DESTROY, // 销毁后
		DEFAULT,
		DISABLED
	}

	@Override
	public boolean updateEngineAppLoaderState(String cacheKey,EngineAppLoaderState state,boolean isVerify){
		if(isVerify){
			EngineAppLoaderState old = cacheAppLoaderState.get(cacheKey);
			if(EngineAppLoaderState.END_DESTROY == state){
				cacheAppLoaderState.remove(cacheKey);
			}else if(EngineAppLoaderState.DISABLED == state && old == EngineAppLoaderState.RUN_ING){
				// 状态迁移 -> RUN_ING -> DISABLED
				cacheAppLoaderState.replace(cacheKey, state);
			}else if(EngineAppLoaderState.RUN_ING == state && old == EngineAppLoaderState.DISABLED){
				// 状态迁移 -> DISABLED -> RUN_ING
				cacheAppLoaderState.replace(cacheKey, state);
			}else{
				if(findNextState(cacheKey) == state && cacheAppLoaderState.containsKey(cacheKey)){
					cacheAppLoaderState.replace(cacheKey, state);
				}else if(!cacheAppLoaderState.containsKey(cacheKey)){
					cacheAppLoaderState.put(cacheKey, state);
				}else{
					error("容器[%s]状态警告！下个状态[%s] - 想变更为[%s]",cacheKey,findNextState(cacheKey),state);
					return false;
				}
			}
			info("容器[%s]状态变更 - 变更前[%s] - 变更后[%s]",cacheKey,old,state);
			return true;
		}else{
			info("容器[%s]状态变更 - 变更前[%s] - 变更后[%s]",cacheKey,getCurrentLoaderState(cacheKey),state);
			if(cacheAppLoaderState.containsKey(cacheKey))
				cacheAppLoaderState.replace(cacheKey, state);
			else
				cacheAppLoaderState.put(cacheKey, state);
			return true;
		}
	}



	@Override
	public boolean updateEngineAppLoaderState(String cacheKey,EngineAppLoaderState state){
		return updateEngineAppLoaderState(cacheKey,state,true);
	}
	@Override
	public EngineAppLoaderState getCurrentLoaderState(String cacheKey){
		return cacheAppLoaderState.get(cacheKey);
	}

	private EngineAppLoaderState findNextState(String cacheKey){
		try{
			for (int i = 0; i < EngineAppLoaderState.values().length; i++) {
				if(EngineAppLoaderState.values()[i] == cacheAppLoaderState.get(cacheKey)){
					return EngineAppLoaderState.values()[i+1];
				}
			}
		}catch(Exception e){
		}
		return null;
	}


	@Override
	public void afterPropertiesSet() throws Exception {
		cacheAppLoaderState = new ConcurrentHashMap<String, EngineAppLoaderState>();
		appsContext = new ConcurrentHashMap<String, EngineAppContext>();
	}


	@Override
	public void destroy() throws Exception {
		if(cacheAppLoaderState != null){
			cacheAppLoaderState.clear();
			cacheAppLoaderState = null;
		}
		if(appsContext != null)
		{
			appsContext.clear();
			appsContext = null;
		}
	}


	@Override
	public void register(String cacheKey, EngineAppContext context) {
		Assert.isTrue(!appsContext.containsKey(cacheKey));
		appsContext.put(cacheKey, context);
	}
	@Override
	public void unregister(String cacheKey){
		if(appsContext.containsKey(cacheKey)){
			appsContext.remove(cacheKey);
		}
	}



	@Override
	public EngineAppContext getEnableAppModelContext(String cacheKey) {
		EngineAppContext appContext = appsContext.get(cacheKey);
		Assert.notNullCode(appContext, ErrorCode.SYSTEM_ERROR,String.format("容器[%s]已释放或者不存在！...", cacheKey));
		EngineAppLoaderState state = appContext.getLoaderState();
		Assert.isTrueCode(state == EngineAppLoaderState.RUN_ING,ErrorCode.SYSTEM_ERROR,String.format("容器[%s]状态错误[%s]！...", cacheKey,state));
		return appContext;
	}



	@Override
	public EngineAppContext getEnableAppModelContext(String projectName, String version) {
		return getEnableAppModelContext(new StringCache(projectName).append(EngineConstant.STR_SPLIT).append(version).toString());
	}

}
